package org.dg;

import org.dg.iag.conf.ApplicationProperties;
import org.dg.iag.server.ActionsServerResource;
import org.dg.iag.server.EntityListServerResource;
import org.dg.iag.server.EntityServerResource;
import org.dg.iag.server.ImportFeedsServerResource;
import org.dg.iag.server.LoginServerResource;
import org.dg.iag.server.LogsServerResource;
import org.dg.iag.server.SettingsInstanceServerResource;
import org.dg.iag.server.SettingsServerResource;
import org.dg.iag.server.StatisticsResource;
import org.dg.iag.server.UserServerResource;
import org.dg.iag.server.UsersServerResource;
import org.dg.iag.util.ApplicationConstants;
import org.dg.iag.util.scheduler.SchedulerManager;
import org.restlet.Application;
import org.restlet.Client;
import org.restlet.Component;
import org.restlet.Context;
import org.restlet.Restlet;
import org.restlet.data.Protocol;
import org.restlet.engine.application.Decoder;
import org.restlet.resource.Directory;
import org.restlet.resource.ServerResource;
import org.restlet.routing.Router;
import org.restlet.routing.Template;
import org.restlet.service.DecoderService;
import org.restlet.util.ServiceList;

public class InitialServer extends ServerResource{
	
	public final static Component component	= new Component();
	
	public static void main(String[] args) throws Exception {
		
		SchedulerManager scheduleManager	= SchedulerManager.getInstance();

		// Create the HTTP server and listen on port 8182
		configureContext( component.getContext(), false );
		
		DecoderService ds		= new DecoderService(true);
		ds.setContext(component.getContext() ) ;
		ds.start();
		
		component.getServices().add( ds );
		
		ServiceList sl	= component.getServices();
//		System.out.println( "Is decoder service enabled ? " + sl );
		
		component.getServers().setContext( configureContext(true, scheduleManager) );
		component.getClients().setContext( configureContext(true, scheduleManager) );
		
		component.getServers().add(Protocol.HTTP, Integer.parseInt(ApplicationProperties.MY_SERVER_PORT));
		component.getClients().add(Protocol.HTTP);
//		
//		Decoder decoder			= new Decoder(component.getClients().getContext() , false, true);
//		decoder.setNext( httpClient );
//		
		component.getClients().add(Protocol.FILE);
		component.getClients().add(Protocol.ZIP);
		
		
		scheduleManager.createJobs();
		scheduleManager.startManager();
		
//		System.out.println( "Connections" +
//		component.getContext().getParameters().getValues("maxConnectionsPerHost") );
		
		//new Server(Protocol.HTTP, 8182, InitialServer.class).start();
		
		// Create a router Restlet that defines routes.
		Router usersRouter = new Router( configureContext( component.getContext(), true ) );
		InitialServer.configureRouteWithParams(usersRouter, ActionsServerResource.class, "/activities", "/start/{start}/howmany/{howmany}");
		
		
		InitialServer.configureRouteWithParams(usersRouter, EntityServerResource.class, "/entity/{entityName}", "", "/filter");
		
		usersRouter.attach("/entity/{entityName}", EntityServerResource.class);
		usersRouter.attach("/entity/{entityName}/format/{formatName}", EntityServerResource.class);
		String path 	= "";
		for ( int i=1; i<=ApplicationConstants.MAX_PARAMS_IN_QUERY; i++ ) {
			path	+= "/filter/{key"+i+"}/{value"+i+"}";
			String entirePath	= "/entity/{entityName}" + path + "/format/{formatName}";
			usersRouter.attach(entirePath, EntityServerResource.class);
		}
		
		
		InitialServer.configureRouteWithParams(usersRouter, EntityListServerResource.class, "/list/{entityName}", "/start/{start}/howmany/{howmany}");
		
		usersRouter.attach("/users", UsersServerResource.class);
		usersRouter.attach("/user/{username}", UserServerResource.class);
		usersRouter.attach("/settingsInstance/{id}", SettingsInstanceServerResource.class);
		usersRouter.attach("/settings", SettingsServerResource.class);
		usersRouter.attach("/importfeeds/{actionName}", ImportFeedsServerResource.class);
		usersRouter.attach("/importfeeds/{actionName}/{param1}", ImportFeedsServerResource.class);
		usersRouter.attach("/logs", LogsServerResource.class);
		usersRouter.attach("/login", LoginServerResource.class, Template.MODE_STARTS_WITH);
//		usersRouter.attach("/html", HttpServerResource.class,Template.MODE_STARTS_WITH);
		
		usersRouter.attach("/stats", StatisticsResource.class);
		
		Application application = new Application( configureContext(true) ) {  
		    @Override  
		    public Restlet createRoot() {  
		    	System.out.println("max threads are !!!! "+ this.getContext().getParameters().getFirst("maxThreads") );
		        return new Directory( configureContext(true), ApplicationConstants.WEBROOT_ABSOLUTE_PATH);  
		    }  
		};  
		
		component.getDefaultHost().attach("/agg", usersRouter);
		component.getDefaultHost().attach("/admin", application);
		Thread thread	= new Thread() {
			@Override
			public void run () {
				try {
					component.start();
				} catch (Exception e) {	
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		};
		
		thread.start();
	}

	public static Context configureContext ( boolean onChildContext ) {
		return configureContext(InitialServer.component.getContext() , onChildContext);
	}
	public static Context configureContext ( boolean onChildContext, SchedulerManager scheduleManager ) {
		return configureContext(InitialServer.component.getContext() , onChildContext, scheduleManager);
	}
	
	
	public static Context configureContext ( Context context, boolean onChildContext ) {
		return configureContext(context, onChildContext, null);
	}
	
	public static Context configureContext ( Context context, boolean onChildContext, SchedulerManager scheduleManager ) {
		if ( onChildContext ) {
			SchedulerManager sm		= (SchedulerManager) context.getAttributes().get(ApplicationConstants.SCHEDULE_MANAGER );
			
			context	= context.createChildContext();
			if ( sm != null ) {
				context.getAttributes().put(ApplicationConstants.SCHEDULE_MANAGER, sm);
			}
		}
		if ( scheduleManager != null ) {
			context.getAttributes().put(ApplicationConstants.SCHEDULE_MANAGER, scheduleManager);
		}
		
		context.getParameters().add("minThreads", "10");
		context.getParameters().add("maxThreads", "250"); 
		context.getParameters().add("maxTotalConnections", "5000");
		context.getParameters().add("maxConnectionsPerHost", "5000");
		context.getParameters().add("threadMaxIdleTimeMs", "130000");
		context.getParameters().add("tcpNoDelay", "true");
		context.getParameters().add("socketTimeout", "120000");
		context.getParameters().add("readTimeout", "120000");
		
		return context;
	}
	
	public static void configureRouteWithParams(Router router, Class resourceClass, String suffix, String prefix) {
		configureRouteWithParams(router, resourceClass, suffix, prefix, null);
	}
	
	public static void configureRouteWithParams(Router router, Class resourceClass, String suffix, String prefix, String keyValuePrefix) {
		String params	= "";
		String kvPrefix	= "";
		if ( keyValuePrefix != null )
			kvPrefix	= keyValuePrefix;
		
		for ( int i=1; i<=ApplicationConstants.MAX_PARAMS_IN_QUERY+1; i++ ) {
			String entirePath	= suffix + params + prefix;
			router.attach(entirePath, resourceClass);
			params	+= kvPrefix + "/{key"+i+"}/{value"+i+"}";
		}
	}

}
